package com.sgzn.sgpay.service.impl;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.sgzn.sgpay.enums.ReturnResultState;
import com.sgzn.sgpay.enums.SgsResponseCode;
import com.sgzn.sgpay.exception.SgpayException;
import com.sgzn.sgpay.model.request.SgsMobileMsgVerifyAddRequest;
import com.sgzn.sgpay.model.request.SgsMobileMsgVerifyDeleteRequest;
import com.sgzn.sgpay.model.request.SgsMobileMsgVerifyQueryRequest;
import com.sgzn.sgpay.model.request.SgsMobileMsgVerifyUpdateRequest;
import com.sgzn.sgpay.model.response.SgsResultResponse;
import com.sgzn.sgpay.persistence.dao.TMobileMsgVerifyMapper;
import com.sgzn.sgpay.persistence.domain.TMobileMsgVerify;
import com.sgzn.sgpay.persistence.domain.TMobileMsgVerifyExample;
import com.sgzn.sgpay.service.SgsMobileMsgVerifyService;
import com.sgzn.sgpay.service.support.SgsResponseUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 手机短信验证管理服务接口实现类
 * @author huangsenguang
 * @version Id: SgsMobileMsgVerifyServiceImpl.java, v 0.1 2018/4/25 21:02 huangsenguang Exp $$
 */
@Service
@Slf4j
public class SgsMobileMsgVerifyServiceImpl implements SgsMobileMsgVerifyService {
    @Autowired
    private TMobileMsgVerifyMapper tMobileMsgVerifyMapper;

    /**
     * 有效时间：一分钟，60000毫秒
     */
    private static long VALID_MS = 60000;

    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public SgsResultResponse<String> addMobileMsgVerify(SgsMobileMsgVerifyAddRequest request) {

//        String verifyCode = MessageUtil.gerateVerifyCode(request.getMobile());
        String verifyCode = "123456";//默认认证码
        int num = 0;
        try{
            TMobileMsgVerify queryMobile = this.queryMobile(request.getMobile());
            if (queryMobile == null) {
                num = addMobileCode(request, verifyCode);
            } else {
                num = updateMobileCode(request.getMobile(), verifyCode);
            }
        }catch (DataAccessException e) {
            log.error("插入响应流水日志异常.{}", e);
        }
        if (num == 1) {
            return SgsResponseUtil.INSTANCE.success(ReturnResultState.SUCCESS.getCode());
        } else {
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C503.getResponseCode(),SgsResponseCode.C503.getResponseDesc(), ReturnResultState.FAIL.getCode());
        }
    }

    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public SgsResultResponse<String> deleteMobileMsgVerify(SgsMobileMsgVerifyDeleteRequest request) {
        SgsResultResponse sgsResponse = new SgsResultResponse();
        TMobileMsgVerifyExample example = new TMobileMsgVerifyExample();
        TMobileMsgVerifyExample.Criteria criteria = example.createCriteria();
        criteria.andMobileEqualTo(request.getMobile());
        int num = 0 ;
        try{
            num =  tMobileMsgVerifyMapper.deleteByExample(example);
        }catch (DataAccessException e) {
            log.error("插入响应流水日志异常.{}", e);
        }
        if (num >= 1) {
            return SgsResponseUtil.INSTANCE.success(ReturnResultState.SUCCESS.getCode());
        } else {
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C503.getResponseCode(),SgsResponseCode.C503.getResponseDesc(), ReturnResultState.FAIL.getCode());
        }
    }

    @Override
    public SgsResultResponse<Boolean> isMobileMsgVerify(SgsMobileMsgVerifyQueryRequest request) {
        SgsResultResponse sgsResponse = new SgsResultResponse();
        try {
            TMobileMsgVerify tMobileMsgVerify = queryMobile(request.getMobile());
            if (tMobileMsgVerify != null && request.getVerifyCode().equals(tMobileMsgVerify.getVerifyCode())) {
                if(!tokenIsValid(tMobileMsgVerify.getUpdatedAt().getTime(),VALID_MS)){
                    throw new SgpayException(SgsResponseCode.C_CODE_OVERTIME.getResponseCode(),
                            SgsResponseCode.C_CODE_OVERTIME.getResponseDesc());
                }
            }else{
                throw new SgpayException(SgsResponseCode.C_CODE_NOT_FOUND.getResponseCode(),
                        SgsResponseCode.C_CODE_NOT_FOUND.getResponseDesc());
            }
            return SgsResponseUtil.INSTANCE.success(true);
        } catch (SgpayException e) {
            log.error("校验验证码 业务异常：", e);
            sgsResponse.setErrorCode(e.getCode());
            sgsResponse.setErrorMsg(e.getDesc());
        } catch (Exception e) {
            log.error("查询手机短信验证 异常：",e);
            sgsResponse.setErrorCode(SgsResponseCode.C_PAY_CALLBACK_ERR.getResponseCode());
            sgsResponse.setErrorMsg(SgsResponseCode.C_PAY_CALLBACK_ERR.getResponseDesc());
        }
        return  sgsResponse;
    }

    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public SgsResultResponse<String> updateMobileMsgVerify(SgsMobileMsgVerifyUpdateRequest request) {
        SgsResultResponse sgsResponse = new SgsResultResponse();
        int num = updateMobileCode(request.getMobile(), request.getVerifyCode());
        if (num >= 1) {
            return SgsResponseUtil.INSTANCE.success(ReturnResultState.SUCCESS.getCode());
        } else {
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C503.getResponseCode(),SgsResponseCode.C503.getResponseDesc(), ReturnResultState.FAIL.getCode());
        }
    }

    private int addMobileCode(SgsMobileMsgVerifyAddRequest request, String verifyCode) {
        try {
            TMobileMsgVerify tMobileMsgVerify = new TMobileMsgVerify();
            tMobileMsgVerify.setMobile(request.getMobile());
            tMobileMsgVerify.setVerifyCode(verifyCode);
            tMobileMsgVerify.setCreatedAt(new Date());
            tMobileMsgVerify.setUpdatedAt(new Date());
            return tMobileMsgVerifyMapper.insertSelective(tMobileMsgVerify);
        } catch (Exception e) {
            log.info("addMobileCode occur Exception:", e);
        }
        return 0;
    }

    private int updateMobileCode(String mobile, String verifyCode) {
        try{
            TMobileMsgVerify record = new TMobileMsgVerify();
            record.setMobile(mobile);
            record.setVerifyCode(verifyCode);
            record.setUpdatedAt(new Date());
            TMobileMsgVerifyExample example = new TMobileMsgVerifyExample();
            TMobileMsgVerifyExample.Criteria criteria = example.createCriteria();
            criteria.andMobileEqualTo(mobile);
            return tMobileMsgVerifyMapper.updateByExampleSelective(record, example);
        }catch (DataAccessException e) {
            log.error("updateMobileCode occur Exception:", e);
        }
        return 0;
    }

    /**
     * 查询手机验证码记录
     * @param mobile
     * @return
     */
    private TMobileMsgVerify queryMobile(String mobile) {
        try {
            TMobileMsgVerify tMobileMsgVerify =null;
            TMobileMsgVerifyExample tMobileMsgVerifyExample = new TMobileMsgVerifyExample();
            tMobileMsgVerifyExample.createCriteria().andMobileEqualTo(mobile);
            List<TMobileMsgVerify> tMobileMsgVerifys = tMobileMsgVerifyMapper.selectByExample(tMobileMsgVerifyExample);
            if (CollectionUtils.isEmpty(tMobileMsgVerifys)) {
                return null;
            }
            tMobileMsgVerify = tMobileMsgVerifys.get(0);
            return tMobileMsgVerify;
        } catch (Exception e) {
            log.info("queryMobile occuer Exception:", e);
        }
        return null;
    }

    /**
     * 判断token是否有效
     * @param before
     * @return
     */
    private boolean tokenIsValid(long before, long vaidTime){
        boolean result = false;
        long current = System.currentTimeMillis();
        long ms = current - before;
        if(ms <= vaidTime){
            result = true;
        }
        return result;
    }
}

